﻿//======================================================================
//
//        Copyright (C) 2002-2008 S.Sams Lifexperience!
//        All rights reserved
//        FileName : Map
//        Description :
//        Created by Sam Shen at 2008/8/2 11:41:08
//        http://lab.travelive.com.cn/
//        E-Mail: S.Sams@msn.com
//
//======================================================================

using System;
using System.IO;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using Travelive.TemplateEngine;

namespace S.Sams.GoogleMap
{
    /// <summary>
    /// 地图操作类 Google Maps API 2.0
    /// </summary>
    public class Maps
    {
        #region 初始化构造函数属性
        /// <summary>
        /// 应用程序认证ID
        /// </summary>
        public string AppID
        {
            get;
            set;
        }

        /// <summary>
        /// 是否使用本地脚本库
        /// </summary>
        public bool IsUseLactionJs
        {
            get;
            set;
        }

        /// <summary>
        /// 是否进行javascript压缩输出
        /// </summary>
        public bool IsPackJavaScript
        {
            get;
            set;
        }

        /// <summary>
        /// 系统初始化入参
        /// </summary>
        public Init SystemInit
        {
            get;
            set;
        }

        /// <summary>
        /// 初始化标注点
        /// </summary>
        public List<Label> Labels
        {
            get;
            set;
        }

        /// <summary>
        /// 设置地图线条组
        /// </summary>
        public List<MapLine> Maplines
        {
            get;
            set;
        }

        private string _gjs = "http://maps.google.com/";
        /// <summary>
        /// 地图引擎文件引用地址, 可设置为 "http://ditu.google.com/", 改为本地地图(部分区域用 maps.google.com 是没有中文部分的数据的)
        /// </summary>
        public string GoogleMapsJsPath
        {
            get {
                if (string.IsNullOrEmpty(_gjs)) return "http://maps.google.com/";

                _gjs = _gjs.ToLower();
                if (!(_gjs.StartsWith("http://") || _gjs.StartsWith("https://"))) _gjs = "http://" + _gjs;
                if (!_gjs.EndsWith("/")) _gjs = _gjs + "/";
                return _gjs;
            }
            set { _gjs = value; }
        }
        #endregion

        /// <summary>
        /// 初始地图类
        /// </summary>
        /// <param name="appid">应用程序认证ID</param>
        /// <param name="systeminit">系统初始化入参</param>
        /// <param name="labels">初始化标注点</param>
        public Maps(string appid, Init systeminit, List<Label> labels)
        {
            AppID = appid;
            IsUseLactionJs = false;
            IsPackJavaScript = true;
            SystemInit = systeminit;
            Labels = labels;
        }

        /// <summary>
        /// 初始地图类
        /// </summary>
        /// <param name="appid">应用程序认证ID</param>
        /// <param name="isuselactionjs">是否使用本地脚本库(一般情况建议设置为 false)</param>
        /// <param name="ispackjavascript">是否进行javascript压缩输出(建议设置为 true)</param>
        /// <param name="systeminit">系统初始化入参</param>
        /// <param name="labels">初始化标注点</param>
        public Maps(string appid, bool isuselactionjs, bool ispackjavascript, Init systeminit, List<Label> labels)
        {
            AppID = appid;
            IsUseLactionJs = isuselactionjs;
            IsPackJavaScript = ispackjavascript;
            SystemInit = systeminit;
            Labels = labels;
        }

        /// <summary>
        /// 初始地图类
        /// </summary>
        /// <param name="appid">应用程序认证ID</param>
        /// <param name="isuselactionjs">是否使用本地脚本库(一般情况建议设置为 false)</param>
        /// <param name="ispackjavascript">是否进行javascript压缩输出(建议设置为 true)</param>
        /// <param name="systeminit">系统初始化入参</param>
        /// <param name="labels">初始化标注点</param>
        /// <param name="maplines">初始化线条</param>
        public Maps(string appid, bool isuselactionjs, bool ispackjavascript, Init systeminit, List<Label> labels, List<MapLine> maplines)
        {
            AppID = appid;
            IsUseLactionJs = isuselactionjs;
            IsPackJavaScript = ispackjavascript;
            SystemInit = systeminit;
            Labels = labels;
            Maplines = maplines;
        }

        /// <summary>
        /// 返回生成地图(Html字符集, 直接输出到页面即可)
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            StringBuilder Html = new StringBuilder();
            if (!CheckParameters()) return string.Empty;
            // 添加地图运行脚本
            Html.Append(BuilderJavaScript(IsUseLactionJs));
            Html.Append("<script type=\"text/javascript\">");

            // 脚本模板化处理
            TemplateDesign tmp = new TemplateDesign(TemplateLoadType.Resource);
            tmp.TempDirPath = Assembly.GetExecutingAssembly().GetName().Name;
            tmp.TemplateFile = "Template.Maps.html";

            tmp.SetAttribute("Help", new TempHelp());
            tmp.SetAttribute("Init", SystemInit);
            //tmp.SetAttribute("Labels", Labels);
            tmp.SetAttribute("ShowMsgName", TempHelp.ShowMsgName(Labels));
            tmp.SetAttribute("LabelsLength", Labels.Count);
            tmp.SetAttribute("FirstLabel", Labels[0]);
            tmp.SetAttribute("MapType", Helper.EnumParse(SystemInit.Maptype));
            tmp.SetAttribute("MapControl", Helper.EnumParse(SystemInit.Mapcontrol));
            tmp.SetAttribute("IsMapControls", SystemInit.IsMapControls);
            tmp.SetAttribute("IsMapScale", SystemInit.IsMapScale);
            tmp.SetAttribute("IsMapView", SystemInit.IsMapView);
            tmp.SetAttribute("MapViewSize", MapViewSize());
            tmp.SetAttribute("IsMapType", SystemInit.IsMapType);
            tmp.SetAttribute("BuildeLabes", TempHelp.BuildeLabes(Labels, SystemInit.IsShowCenterMsg, SystemInit.ZoomIn));
            tmp.SetAttribute("IsDrawLine", (SystemInit.IsAddLine || Maplines != null));
            tmp.SetAttribute("DefaultLine", DrawingDefaultLine());
            tmp.SetAttribute("DrawingAddLine", DrawingAddLine());

            Html.Append(JavascriptPack(tmp.ToString()));
            Html.Append("</script>");
            return Html.ToString();
        }

        #region 生成图片地址
        /// <summary>
        /// 返回当前地图转换成图片有效路径.
        /// </summary>
        /// <param name="width">图片宽度(不允许超过600px)</param>
        /// <param name="height">国片高度(不允许超过600px)</param>
        /// <returns></returns>
        public string ToImagePath(int width, int height)
        {
            return MapToImageString(width, height);
        }

        /// <summary>
        /// 生成图片地址(图片不支持附加的线条组, 只支持Label点之间线条)
        /// </summary>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <returns></returns>
        private string MapToImageString(int width, int height)
        {
            // 标注点线条
            //http://maps.google.com/staticmap?
            //center=23.119048,113.299942&
            //markers=23.110207183273666,113.30028533935547,greena|23.110300,113.296400,redb&
            //path=rgba:0x0000FF80,weight:5|23.110207183273666,113.30028533935547|23.110300,113.296400&
            //zoom=13&
            //size=600x600&
            //key=ABQIAAAAjU0EJWnWPMv7oQ-jjS7dYxSPW5CJgpdgO_s4yyMovOaVh_KvvhSfpvagV18eOyDWu7VytS6Bi1CWxw

            if (!CheckParameters()) return string.Empty;
            int i = 0;
            List<string> path = new List<string>();

            path.Add("center=" + Labels[0].X.ToString() + "," + Labels[0].Y.ToString());

            string markers = string.Empty;
            foreach (Label lab in Labels)
            {
                if (lab.Visible)
                {
                    if (string.IsNullOrEmpty(markers))
                    {
                        markers = lab.X.ToString() + "," + lab.Y.ToString() + "," + GetRamColorName() + IndexNumber(i);
                    }
                    else
                    {
                        markers += "|" + lab.X.ToString() + "," + lab.Y.ToString() + "," + GetRamColorName() + IndexNumber(i);
                    }
                }
                i++;
            }
            path.Add("markers=" + markers);

            if(SystemInit.IsAddLine)
            {
                markers = string.Empty;
                foreach (Label lab in Labels)
                {
                    if(lab.Visible) markers += "|" + lab.X.ToString() + "," + lab.Y.ToString();
                }
                if (SystemInit.IsAddLineEnd) markers += "|" + Labels[0].X.ToString() + "," + Labels[0].Y.ToString();
            }
            path.Add("path=rgb:0x" + SystemInit.AddLine16Color.Substring(1).ToLower() + ",weight:" + SystemInit.AddLineWidth.ToString() + markers);

            path.Add("zoom=" + SystemInit.ZoomIn.ToString());
            path.Add(string.Format("size={0}x{1}", (width > 600 ? 600 : width).ToString(), (height > 600 ? 600 : height).ToString()));
            //path.Add("format=png32");
            path.Add("key=" + AppID);
            return GoogleMapsJsPath + "/staticmap?" + string.Join("&", path.ToArray());
        }
        #endregion

        #region 产生随机颜色
        /// <summary>
        /// 产生随机颜色
        /// </summary>
        /// <returns></returns>
        private string GetRamColorName()
        {
            return "red";

            //"black", "brown", "green", "purple", "yellow", "blue", "gray", "orange", "red", "white" 
            /*string[] color = { "red", "green", "yellow", "blue", "orange" };
            System.Threading.Thread.Sleep(100);
            return color[new Random().Next(0,color.Length-1)];*/
        }
        #endregion

        #region 产生序列号字母
        /// <summary>
        /// 产生序列号字母
        /// </summary>
        /// <param name="indexSelect"></param>
        /// <returns></returns>
        private string IndexNumber(int indexSelect)
        {
            string Chars = "ABCDEFGHIJKLMNOPQRSTUVWSYZ";
            int si = (indexSelect >= Chars.Length ? (indexSelect / Chars.Length) : indexSelect);
            return string.Format("{0}", Chars[si].ToString().ToLower());
        }
        #endregion

        #region 进行 javascript 压缩
        /// <summary>
        /// 进行 javascript 压缩
        /// </summary>
        /// <param name="js">javascript脚本</param>
        /// <returns></returns>
        private string JavascriptPack(string js)
        {
            if (!IsPackJavaScript) return js;

            JavaScriptPack.ECMAScriptPacker p = new JavaScriptPack.ECMAScriptPacker(JavaScriptPack.ECMAScriptPacker.PackerEncoding.Normal, true, false);
            return p.Pack(js);
        }
        #endregion

        #region 返回客户端可调用的javascript函数列表
        /// <summary>
        /// 返回客户端可调用的javascript函数列表 string[标注点返回的函数,标注点名称]
        /// </summary>
        /// <returns></returns>
        public List<JavascriptFunction> CallFunction()
        {
            List<JavascriptFunction> refun = new List<JavascriptFunction>();
            if (CheckParameters())
            {
                int i=0;
                foreach (Label lab in Labels)
                {
                    if (lab.Visible)
                    {
                        refun.Add(new JavascriptFunction() { ID = i, Function = "mapshowmsg" + i.ToString() + "()", Name = lab.Name });
                    }
                    i++;
                }
            }
            return refun;
        }
        #endregion

        #region 添加附加线条
        private string DrawingAddLine()
        {
            if (Maplines != null)
            {
                StringBuilder Html = new StringBuilder();
                int j = 0;
                foreach (MapLine mapline in Maplines)
                {
                    if (mapline.Labels == null) continue;
                    if (mapline.Labels.Count == 0) continue;
                    Html.Append("var polyaddline" + j.ToString() + " = new GPolyline([");

                    int i = 0;
                    foreach (Label item in mapline.Labels)
                    {
                        if (i.Equals(0))
                        {
                            Html.Append("new GLatLng(" + item.X.ToString() + "," + item.Y.ToString() + ")");
                        }
                        else
                        {
                            Html.Append(",new GLatLng(" + item.X.ToString() + "," + item.Y.ToString() + ")");
                        }
                        i++;
                    }
                    Html.Append("], \"" + mapline.Color16Code + "\", " + mapline.LineWidth + ");map.addOverlay(polyaddline" + j.ToString() + ");");

                    j += 1;
                }
                return Html.ToString();
            }
            return "";
        }
        #endregion

        #region 添加默认线条
        private string DrawingDefaultLine()
        {
            if (Labels.Count > 0 && SystemInit.IsAddLine)
            {
                StringBuilder Html = new StringBuilder();
                Html.Append("var polyline = new GPolyline([");
                int i=0;
                foreach (Label item in Labels)
                {
                    if (item.Visible)
                    {
                        if (i.Equals(0))
                        {
                            Html.Append("new GLatLng(" + item.X.ToString() + "," + item.Y.ToString() + ")");
                        }
                        else
                        {
                            Html.Append(",new GLatLng(" + item.X.ToString() + "," + item.Y.ToString() + ")");
                        }
                    }
                    i++;
                }
                if (SystemInit.IsAddLineEnd)
                {
                    Html.Append(",new GLatLng(" + Labels[0].X.ToString() + "," + Labels[0].Y.ToString() + ")");
                }
                Html.Append("], \"" + SystemInit.AddLine16Color + "\", " + SystemInit.AddLineWidth + ");map.addOverlay(polyline);");
                return Html.ToString();
            }
            return "";
        }
        #endregion

        #region 设置视图大小
        /// <summary>
        /// 设置预览图大小 
        /// </summary>
        /// <returns></returns>
        private string MapViewSize()
        {
            if (SystemInit.MapViewWidth.Equals(0) || SystemInit.MapViewHeight.Equals(0))
            {
                return "";
            }
            return "new GSize(" + SystemInit.MapViewWidth + "," + SystemInit.MapViewHeight + ")";
        }
        #endregion

        #region 生成 Javascript 脚本
        /// <summary>
        /// 生成 Javascript 脚本
        /// </summary>
        /// <param name="isLoadLactionJs">是否调用本地脚本,则直接引用GooglMap调用脚本</param>
        /// <returns></returns>
        public string BuilderJavaScript(bool isLoadLactionJs)
        {
            if (isLoadLactionJs)
            {
                using (Stream GetStream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("S.Sams.GoogleMap.JavaScript.Map.html"))
                {
                    using (StreamReader ReadStream = new StreamReader(GetStream))
                    {
                        return "<script type=\"text/javascript\">" + JavascriptPack(ReadStream.ReadToEnd()) + "</script>";
                    }
                }
            }
            return string.Format("<script src=\"" + GoogleMapsJsPath + "/maps?file=api&amp;v=2&amp;key={0}\" type=\"text/javascript\"></script>", AppID.Trim());
        }
        #endregion

        #region 检测当前入参是否正常
        /// <summary>
        /// 检测当前入参是否正常
        /// </summary>
        /// <returns></returns>
        public bool CheckParameters()
        {
            if (string.IsNullOrEmpty(AppID)) return false;
            if (Labels == null) return false;
            if (Labels.Count == 0) return false;
            return true;
        }
        #endregion
    }
}
